package com.milkshopbackend.milkshop.Service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.milkshopbackend.milkshop.Service.CategoryService;
import com.milkshopbackend.milkshop.common.RedisConstants;
import com.milkshopbackend.milkshop.entity.Category;
import com.milkshopbackend.milkshop.entity.CategoryDTO;
import com.milkshopbackend.milkshop.mapper.CetegoryMapper;
import com.milkshopbackend.milkshop.util.CacheClient;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {
    private final CetegoryMapper categoryMapper;
    private final CacheClient cacheClient;
    private final RedisTemplate<String, Object> redisTemplate;

    public CategoryServiceImpl(CetegoryMapper categoryMapper, CacheClient cacheClient, RedisTemplate<String, Object> redisTemplate) {
        this.categoryMapper = categoryMapper;
        this.cacheClient = cacheClient;
        this.redisTemplate = redisTemplate;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<CategoryDTO> listWithTree() {
        log.info("获取分类树形结构");

        // 尝试从缓存获取
        List<CategoryDTO> cachedTree = cacheClient.getWithLogicalExpire(
            RedisConstants.CATEGORY_TREE_KEY,
            "tree",
            List.class,
            id -> {
                // 缓存未命中，查询数据库
                List<Category> categories = categoryMapper.selectList(null);
                return buildTree(categories);
            },
            RedisConstants.CATEGORY_TREE_TTL,
            TimeUnit.SECONDS
        );

        if (cachedTree != null) {
            return cachedTree;
        }

        // 如果缓存重建失败，直接查询数据库
        List<Category> categories = categoryMapper.selectList(null);
        return buildTree(categories);
    }

    @Override
    public CategoryDTO getById(Long id) {
        log.info("根据ID获取分类, id: {}", id);
        
        // 尝试从缓存获取
        return cacheClient.getWithPassThrough(
            RedisConstants.CATEGORY_KEY_PREFIX,
            id.toString(),
            CategoryDTO.class,
            key -> {
                Category category = categoryMapper.selectById(Long.valueOf(key));
                if (category == null) {
                    return null;
                }
                return convertToDTO(category);
            },
            RedisConstants.CATEGORY_TTL,
            TimeUnit.SECONDS
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(CategoryDTO categoryDTO) {
        log.info("创建分类, categoryDTO: {}", categoryDTO);
        // 参数校验
        validateCategory(categoryDTO);

        Category category = new Category();
        BeanUtils.copyProperties(categoryDTO, category);

        // 设置层级
        if (category.getParentId() == null || category.getParentId() == 0L) {
            category.setLevel(1);
        } else {
            Category parent = categoryMapper.selectById(category.getParentId());
            if (parent == null) {
                throw new RuntimeException("父分类不存在");
            }
            category.setLevel(parent.getLevel() + 1);
        }

        categoryMapper.insert(category);
        // 清理缓存
        redisTemplate.delete(RedisConstants.CATEGORY_TREE_KEY);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Long id, CategoryDTO categoryDTO) {
        log.info("更新分类, id: {}, categoryDTO: {}", id, categoryDTO);
        // 参数校验
        validateCategory(categoryDTO);

        Category existCategory = categoryMapper.selectById(id);
        if (existCategory == null) {
            throw new RuntimeException("分类不存在");
        }

        Category category = new Category();
        BeanUtils.copyProperties(categoryDTO, category);
        category.setId(id);

        // 如果修改了父分类，需要重新计算层级
        if (!Objects.equals(existCategory.getParentId(), category.getParentId())) {
            if (category.getParentId() == null || category.getParentId() == 0L) {
                category.setLevel(1);
            } else {
                Category parent = categoryMapper.selectById(category.getParentId());
                if (parent == null) {
                    throw new RuntimeException("父分类不存在");
                }
                category.setLevel(parent.getLevel() + 1);
            }
        }

        categoryMapper.updateById(category);
        // 清理缓存
        redisTemplate.delete(RedisConstants.CATEGORY_TREE_KEY);
        redisTemplate.delete(RedisConstants.CATEGORY_KEY_PREFIX + id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        log.info("删除分类, id: {}", id);
        // 检查是否存在子分类
        LambdaQueryWrapper<Category> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Category::getParentId, id);
        Long count = categoryMapper.selectCount(wrapper);
        if (count > 0) {
            throw new RuntimeException("存在子分类，无法删除");
        }

        categoryMapper.deleteById(id);
        // 清理缓存
        redisTemplate.delete(RedisConstants.CATEGORY_TREE_KEY);
        redisTemplate.delete(RedisConstants.CATEGORY_KEY_PREFIX + id);
    }

    private List<CategoryDTO> buildTree(List<Category> categories) {
        Map<Long, CategoryDTO> dtoMap = new HashMap<>();
        List<CategoryDTO> result = new ArrayList<>();

        // 转换为DTO
        for (Category category : categories) {
            CategoryDTO dto = convertToDTO(category);
            dtoMap.put(dto.getId(), dto);
        }

        // 构建树形结构
        for (CategoryDTO dto : dtoMap.values()) {
            if (dto.getParentId() == null || dto.getParentId() == 0L) {
                result.add(dto);
            } else {
                CategoryDTO parent = dtoMap.get(dto.getParentId());
                if (parent != null) {
                    List<CategoryDTO> children = parent.getChildren();
                    if (children == null) {
                        children = new ArrayList<>();
                        parent.setChildren(children);
                    }
                    children.add(dto);
                }
            }
        }

        // 对每个层级的分类进行排序
        sortCategories(result);

        return result;
    }

    private void sortCategories(List<CategoryDTO> categories) {
        if (CollectionUtils.isEmpty(categories)) {
            return;
        }

        // 对当前层级排序
        categories.sort(Comparator.comparing(CategoryDTO::getSort));

        // 递归排序子分类
        for (CategoryDTO category : categories) {
            List<CategoryDTO> children = category.getChildren();
            if (children != null) {
                sortCategories(children);
            }
        }
    }

    private CategoryDTO convertToDTO(Category category) {
        CategoryDTO dto = new CategoryDTO();
        BeanUtils.copyProperties(category, dto);
        return dto;
    }

    private void validateCategory(CategoryDTO categoryDTO) {
        if (StringUtils.isEmpty(categoryDTO.getName())) {
            throw new RuntimeException("分类名称不能为空");
        }
        if (categoryDTO.getSort() == null) {
            categoryDTO.setSort(0);
        }
    }
}
